#pragma once

#include "Sock.hpp"
#include "Err.hpp"
#include "Log.hpp"

#include <functional>

static uint16_t defaultport = 8080;

class HttpServer; //前置声明
using func_t = std::function<std::string(std::string&)>;

class ThreadData
{
public:
    ThreadData(int sock, const std::string& ip, const uint16_t port, HttpServer* hsvr)
        :_sock(sock), _ip(ip), _port(port), _hsvr(hsvr)
    {}

    ~ThreadData(){}
public:
    std::string _ip;
    uint16_t _port;
    int _sock;
    HttpServer* _hsvr;
};

class HttpServer
{
public:
    HttpServer(func_t func, const uint16_t port = defaultport)
        : _port(port), _func(func)
    {
    }

    void ServerInit()
    {
        // 创建套接字
        _listensock.Socket();
        // 绑定
        _listensock.Bind(_port);
        // 监听
        _listensock.Listen();
    }

    static void *threadRoutine(void *args)
    {
        pthread_detach(pthread_self()); //线程分离
        ThreadData* td = static_cast<ThreadData*>(args); //类型转换

        //线程调用业务
        td->_hsvr->HandlerHttpRequest(td->_sock);

        delete td;
        return nullptr;
    }

    void HandlerHttpRequest(int sock)
    {
        char buffer[4096]; //缓冲区
        std::string request; //数据的请求

        //获取请求数据:
        ssize_t n = recv(sock, buffer, sizeof(buffer) - 1, 0); //先将网络的数据全部获取
        if(n > 0)
        {
            buffer[n] = '\0';
            request += buffer;

            std::string response = _func(request); //回调，业务处理，处理的结果返回存储
            send(sock, response.c_str(), response.size(), 0); //将数据回响返还客户端
        }
        else
        {
            //要么客户端关闭，要么读取出错
            logMessage(Info, "client quit...");
        }
    }

    void Start()
    {
        while (true)
        {
            std::string clientip;
            uint16_t clientport;
            // 连接
            int sock = _listensock.Accept(&clientip, &clientport);
            if (sock < 0)
                continue;

            // 创建多线程
            pthread_t tid;
            ThreadData* td = new ThreadData(sock, clientip, clientport, this);
            pthread_create(&tid, nullptr, threadRoutine, td);
        }
    }

    ~HttpServer() {}

private:
    uint16_t _port;
    Sock _listensock;
    func_t _func;
};